package com.nutiteq.labels;

import java.io.IOException;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDletStateChangeException;

import com.nutiteq.MapComponent;
import com.nutiteq.components.OnMapElement;
import com.nutiteq.components.Place;
import com.nutiteq.components.PlaceIcon;
import com.nutiteq.components.Placemark;
import com.nutiteq.components.WgsPoint;
import com.nutiteq.controls.ControlKeys;
import com.nutiteq.listeners.MapListener;
import com.nutiteq.listeners.OnMapElementListener;
import com.nutiteq.log.Log;
import com.nutiteq.maps.CloudMade;
import com.nutiteq.utils.DummyStarter;
import com.nutiteq.utils.InitializedCanvas;
import com.nutiteq.utils.Utils;

public class CustomCanvas extends Canvas implements InitializedCanvas, MapListener,
    CommandListener, OnMapElementListener {
  private Image splash;

  private final Timer timer;
  private Thread starter;

  private final CustomCanvas instance;

  private static MapComponent mapDisplay;

  private boolean initialized;

  private Command exit;

  private Place[] places;

  private static final Random R = new Random();

  public CustomCanvas() {
    instance = this;
    try {
      splash = Image.createImage("/splash.png");
    } catch (final IOException e) {
      e.printStackTrace();
    }

    timer = new Timer();
    timer.schedule(new TimerTask() {
      public void run() {
        starter = new Thread(new DummyStarter(CustomElements.instanse, instance));
        starter.start();
      }
    }, 3000);
    mapDisplay = new MapComponent("abcdtrial", CustomElements.instanse, getWidth(), getHeight(),
        new WgsPoint(24.746704, 59.429013), 7);
  }

  public void initialize() {

    getMapDisplay().startMapping();

    getMapDisplay().defineControlKey(ControlKeys.MOVE_UP_KEY, -1);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_DOWN_KEY, -2);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_LEFT_KEY, -3);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_RIGHT_KEY, -4);
    getMapDisplay().defineControlKey(ControlKeys.SELECT_KEY, -5);
    getMapDisplay().defineControlKey(ControlKeys.ZOOM_OUT_KEY, Canvas.KEY_NUM1);
    getMapDisplay().defineControlKey(ControlKeys.ZOOM_IN_KEY, Canvas.KEY_NUM3);
    //MPowerPlayer
    getMapDisplay().defineControlKey(ControlKeys.MOVE_UP_KEY, 38);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_DOWN_KEY, 40);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_LEFT_KEY, 37);
    getMapDisplay().defineControlKey(ControlKeys.MOVE_RIGHT_KEY, 39);
    getMapDisplay().defineControlKey(ControlKeys.SELECT_KEY, 10);

    mapDisplay.setTouchClickTolerance(6);

    if (hasPointerEvents()) {
      getMapDisplay().showDefaultOnScreenZoomControls();
      //getMapDisplay().looseFocusOnDrag(true);
    } else {
      getMapDisplay().showDefaultCursor();
    }

    getMapDisplay().showZoomLevelIndicator(false);

    getMapDisplay().setMapListener(this);
    getMapDisplay().setOnMapElementListener(this);

    final Image doubleTmp = Utils.createImage("/double_place.png");
    final Placemark defaultIcon = new PlaceIcon(Image.createImage(doubleTmp, 0, 0, 32, 32, 0));
    final Placemark activeIcon = new PlaceIcon(Image.createImage(doubleTmp, 32, 0, 32, 32, 0));

    places = new Place[] {
        new Place(0, new BalloonLabel("James Bond - 007", "08:23 07.07.2007"), new PersonPlacemark(
            "007 - Bond"), new WgsPoint(24.764580, 59.437420)),
        new Place(0, new ClickTestLabel(), defaultIcon, activeIcon, new WgsPoint(24.279785,
            58.773895)) };

    getMapDisplay().addPlaces(places);

    exit = new Command("Exit", Command.EXIT, 0);

    addCommand(exit);

    setCommandListener(this);

    initialized = true;
    repaint();
  }

  protected void paint(final Graphics g) {
    if (!initialized) {
      //paint splash
      g.setColor(0xFFFFFFFF);
      g.setClip(0, 0, getWidth(), getHeight());
      g.fillRect(0, 0, getWidth(), getHeight());
      g.drawImage(splash, (getWidth() - splash.getWidth()) / 2,
          (getHeight() - splash.getHeight()) / 2, Graphics.TOP | Graphics.LEFT);
      return;
    }

    getMapDisplay().paint(g);
  }

  protected void keyPressed(final int keyCode) {
    if (!initialized) {
      return;
    }

    if (keyCode == Canvas.KEY_NUM7) {
      final Place[] visiblePlaces = mapDisplay.getVisiblePlaces();
      Log.debug("Visible places count " + visiblePlaces.length);
      if (visiblePlaces.length == 0) {
        return;
      }

      final int index = Math.abs(R.nextInt() % visiblePlaces.length);
      final Place random = visiblePlaces[index];
      mapDisplay.focusOnPlace(random);
    } else {
      mapDisplay.keyPressed(keyCode);
    }
  }

  protected void keyReleased(final int keyCode) {
    if (!initialized) {
      return;
    }
    getMapDisplay().keyReleased(keyCode);
  }

  protected void keyRepeated(final int keyCode) {
    if (!initialized) {
      return;
    }
    getMapDisplay().keyRepeated(keyCode);
  }

  protected void pointerDragged(final int x, final int y) {
    if (!initialized) {
      return;
    }
    getMapDisplay().pointerDragged(x, y);
  }

  protected void pointerPressed(final int x, final int y) {
    if (!initialized) {
      return;
    }
    getMapDisplay().pointerPressed(x, y);
  }

  protected void pointerReleased(final int x, final int y) {
    if (!initialized) {
      return;
    }
    getMapDisplay().pointerReleased(x, y);
  }

  public void mapClicked(final WgsPoint p) {
    System.out.println("mapClicked " + p);
  }

  public void mapMoved() {

  }

  public void needRepaint(final boolean mapIsComplete) {
    repaint();
  }

  public void commandAction(final Command cmd, final Displayable d) {
    try {
      mapDisplay.stopMapping();
      CustomElements.instanse.destroyApp(true);
    } catch (final MIDletStateChangeException ignore) {
    }
  }

  public void elementClicked(final OnMapElement p) {
    System.out.println("place clicked");
  }

  public void elementEntered(final OnMapElement p) {
    // TODO Auto-generated method stub

  }

  public void elementLeft(final OnMapElement p) {
    // TODO Auto-generated method stub

  }

  public static MapComponent getMapDisplay() {
    return mapDisplay;
  }
}
